#BD_Main_C
#include "BD_basis.h"
#include "BD_game.h"
#include "BD_animation.h"

int main()
{
	Game game;
	srand(time(NULL));

	if(SDL_Initialization() == false)
	{
		printf("Error! Initialization\n");
		return false;
	}
	if(SDL_Load_Texture_Audio_TTF() == false)
	{
		printf("Error! Loading Textures\n");
		return false;
	}

	Game_Initialization(&game);

	if(Import_Levels(&game) == false)
	{
		printf("Error! Importing Levels\n");
		return false;
	}
	
	Game_Intro(&game);

	while(game.state != FINISH)
	{
		game.miner.prevTime = game.miner.curTime;
		game.miner.curTime = SDL_GetTicks();
		game.miner.elapsedTime += game.miner.curTime - game.miner.prevTime;

		if((int)(game.level->totalTime - game.miner.elapsedTime) < 0)
			game.state = LEVELAGAIN;

		Get_Event(&game);

		if(game.state == CHEAT)
			Cheat_Game(&game);

		if(game.state == PAUSE)
			game.miner.elapsedTime -= game.miner.curTime - game.miner.prevTime;

		if(game.state == CONTINUE)
		{
			Update_Miner(&game);
			Update_Objects(&game);
			Update_Score_Level(&game);
			Do_Render(&game);
		}

		if(game.state == LEVELUP)
		{
			game.miner.collectedDiamond = 0;
			game.state = CONTINUE;

			if(game.panel.cur_level != 0)
				game.level = game.level->next;
			game.panel.cur_level++;

			if(game.state == CONTINUE && game.level != NULL)
			{
				Set_Textures(&game);
				Set_Music(&game);
				for(int i=0; i < game.level->row; ++i)
					for(int j=0; j < game.level->column; ++j)
						if(game.level->map[i][j].id == MINER)
							game.miner.posRect.x = j * CELL_SIZE , game.miner.posRect.y = i * CELL_SIZE;
				
				Level_Show(&game);
				game.miner.elapsedTime = 0;
				game.miner.curTime = SDL_GetTicks();
			}
			else if(game.level == NULL)
			{
				game.state = FINISH;
				Game_Final(&game,0);
			}
		}

		if(game.state == LEVELAGAIN)
		{
			Level_Again(&game,game.level->id);
			Set_Music(&game);
			for(int i=0; i < game.level->row; ++i)
				for(int j=0; j < game.level->column; ++j)
					if(game.level->map[i][j].id == MINER)
						game.miner.posRect.x = j * CELL_SIZE , game.miner.posRect.y = i * CELL_SIZE;
		}

		if(game.miner.health < 1)
		{
			game.state = FINISH;
			Game_Final(&game,1);
		}
	}

	SDL_DestroyTextures_And_Quit(&game);
	return 0;
}
# Animation_C
#include "BD_animation.h"
#include "BD_game.h"

void Game_Intro(Game *g)
{
	Objects button,s1cloud,s2cloud,m1cloud,b1cloud,b2cloud;
	Mix_Music *introMusic;
	bool enter = false , howto = false;
	int cloud_size,i=0;
	int buttonarr[3][2] = {
		{1000*WINDOW_WIDTH/2327,1000*WINDOW_HEIGHT/1853},
		{1000*WINDOW_WIDTH/2327-100*WINDOW_WIDTH/1207,1000*WINDOW_HEIGHT/1853+10*WINDOW_HEIGHT/158},
		{1000*WINDOW_WIDTH/2327,1000*WINDOW_HEIGHT/1853+20*WINDOW_HEIGHT/158}
	};

	introMusic = Mix_LoadMUS(MUSIC_FILE_PATH"/Title_Screen.mp3");
	button.cropRect.x = 98 , button.cropRect.y = 64*6;
	button.cropRect.w = button.cropRect.h = 16;
	button.posRect.w = button.posRect.h = WINDOW_WIDTH/32;

	cloud_size = WINDOW_WIDTH / 32;
	s1cloud.cropRect.x = 0 , m1cloud.cropRect.x = 16 , b1cloud.cropRect.x = 48;
	s1cloud.cropRect.y = m1cloud.cropRect.y = b1cloud.cropRect.y = 64*6;
	s1cloud.cropRect.w = 16 , m1cloud.cropRect.w = 32 , b1cloud.cropRect.w = 50;
	s1cloud.cropRect.h = m1cloud.cropRect.h = b1cloud.cropRect.h = 16;
	s1cloud.posRect.x = WINDOW_WIDTH , m1cloud.posRect.x = WINDOW_WIDTH/2 , b1cloud.posRect.x = WINDOW_WIDTH/4;
	s1cloud.posRect.y = 3*WINDOW_HEIGHT/10 , m1cloud.posRect.y = WINDOW_HEIGHT/5 , b1cloud.posRect.y = WINDOW_HEIGHT/25;
	s1cloud.posRect.w = 2*cloud_size , m1cloud.posRect.w = 4 * cloud_size , b1cloud.posRect.w = 8 * cloud_size;
	s1cloud.posRect.h = 5*cloud_size/4 , m1cloud.posRect.h = 2 *cloud_size , b1cloud.posRect.h = 3 * cloud_size;
	s2cloud = s1cloud;
	s2cloud.posRect.x = WINDOW_WIDTH/3;
	s2cloud.posRect.y = WINDOW_HEIGHT/2;
	b2cloud = b1cloud;
	b2cloud.posRect.x = 3*WINDOW_WIDTH/4 , b2cloud.posRect.y = WINDOW_HEIGHT/50;

	Mix_PlayMusic(introMusic,-1);
	Mix_VolumeMusic(16);

	while(g->state != FINISH && enter == false)
	{
		while(SDL_PollEvent(&event))
		{
			if(event.type == SDL_QUIT)
				g->state = FINISH;
			else if(event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_ESCAPE)
				g->state = FINISH;
			else if(event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_RETURN)
				enter = true;
			else if(event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_UP && i>0 && howto == false)
					i--;
			else if(event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_DOWN && i<2 && howto == false)
					i++;
		}

		button.posRect.x = buttonarr[i][0];
		button.posRect.y = buttonarr[i][1];

		if(enter && button.posRect.y == buttonarr[1][1])
		{
			if(howto == false)
				howto = true;
			else
				howto = false;
			enter = false;
		}
		else if(enter && button.posRect.y == buttonarr[0][1] && howto == false)
			enter = true;
		else if(enter && button.posRect.y == buttonarr[2][1] && howto == false)
			g->state = FINISH;

		s1cloud.posRect.x -= 2 , s2cloud.posRect.x -= 2;
		m1cloud.posRect.x -- , b1cloud.posRect.x -- , b2cloud.posRect.x --;

		if(s1cloud.posRect.x + s1cloud.posRect.h < 0)
			s1cloud.posRect.x = WINDOW_WIDTH;
		if(s2cloud.posRect.x + s2cloud.posRect.h < 0)
			s2cloud.posRect.x = WINDOW_WIDTH;
		if(m1cloud.posRect.x + m1cloud.posRect.w < 0)
			m1cloud.posRect.x = WINDOW_WIDTH;
		if(b1cloud.posRect.x + b1cloud.posRect.w < 0)
			b1cloud.posRect.x = WINDOW_WIDTH;
		if(b2cloud.posRect.x + b2cloud.posRect.w < 0)
			b2cloud.posRect.x = WINDOW_WIDTH;

		SDL_RenderClear(renderer);
		if(howto == false)
		{
			SDL_RenderCopy(renderer,introTex,NULL,NULL);
			SDL_RenderCopy(renderer,g->tex,&button.cropRect,&button.posRect);
		}
		else
			SDL_RenderCopy(renderer,howtoTex,NULL,NULL);
		SDL_RenderCopy(renderer,g->tex,&s1cloud.cropRect,&s1cloud.posRect);
		SDL_RenderCopy(renderer,g->tex,&s2cloud.cropRect,&s2cloud.posRect);
		SDL_RenderCopy(renderer,g->tex,&m1cloud.cropRect,&m1cloud.posRect);
		SDL_RenderCopy(renderer,g->tex,&b1cloud.cropRect,&b1cloud.posRect);
		SDL_RenderCopy(renderer,g->tex,&b2cloud.cropRect,&b2cloud.posRect);
		SDL_RenderPresent(renderer);
	}
}

void Game_Final(Game *g, int situation)
{
	SDL_Texture *finalText;
	SDL_Rect textPos;
	bool quit = false;
	char buffer[16];

	Mix_PlayMusic(ending_music,-1);
	Mix_VolumeMusic(MUSIC_VOL);

	if(situation == 0)	sprintf(buffer,"%s","You Win");
	else	sprintf(buffer,"%s","Game Over");

	SDL_Surface *sur = TTF_RenderText_Solid(font,buffer,g->panel.c);
	finalText = SDL_CreateTextureFromSurface(renderer,sur);
	SDL_FreeSurface(sur);

	textPos.x = 16*WINDOW_WIDTH/40 , textPos.y = WINDOW_HEIGHT/20;
	textPos.w = WINDOW_WIDTH/5 , textPos.h = WINDOW_HEIGHT/10;
	g->panel.posScore.x = 65*WINDOW_WIDTH/160 , g->panel.posScore.y = 3*WINDOW_HEIGHT/10;

	while(!quit)
	{
		while(SDL_PollEvent(&event))
			if(event.type == SDL_QUIT || (event.type == SDL_KEYDOWN  && (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE || event.key.keysym.scancode == SDL_SCANCODE_RETURN)))
				quit = true;

		SDL_RenderClear(renderer);
		SDL_RenderCopy(renderer,finalTex,NULL,NULL);
		SDL_RenderCopy(renderer,finalText,NULL,&textPos);
		SDL_RenderCopy(renderer,g->panel.textScore,NULL,&g->panel.posScore);
		SDL_RenderPresent(renderer);
	}
}

void Level_Final(Game *g)
{
	int add = -4,count = 0;
	Uint32 prev_time = 0,cur_time = 0;

	g->miner.cropRect.x = g->miner.cropRect.w;
	g->miner.cropRect.y = 0;

	Mix_PauseMusic();
	Mix_VolumeChunk(bonusScoreEffect,128);
	Mix_PlayChannel(-1,bonusScoreEffect,0);
	
	cur_time = SDL_GetTicks();
	prev_time = cur_time;

	while(cur_time - prev_time < 5000)
	{
		cur_time = SDL_GetTicks();

		if((g->level->totalTime - g->miner.elapsedTime)/1000 > 0)
		{
			g->panel.score++;
			g->miner.elapsedTime += 1000;
		}
		else
			Mix_VolumeChunk(bonusScoreEffect,0);
		
		if(count == -CELL_SIZE)
			add = 4;
		else if(count == 0)
			add = -4;

		g->miner.posRect.y += add;
		count += add;

		Update_Score_Level(g);
		Do_Render(g);
		SDL_Delay(10);
	}

	Mix_HaltChannel(-1);
}

void Level_Show(Game *g)
{
	int i,j;

	g->miner.cameraRect.x = g->level->column * CELL_SIZE - WINDOW_WIDTH;
	g->miner.cameraRect.y = g->level->row * CELL_SIZE - WINDOW_HEIGHT;

	while(g->miner.cameraRect.x > 0 || g->miner.cameraRect.y > 0)
	{
		SDL_RenderClear(renderer);

		for(i=0;i<g->level->row;++i)
			for(j=0;j<g->level->column;++j)
			{
				g->level->map[i][j].drawingRect.x = g->level->map[i][j].posRect.x - g->miner.cameraRect.x;
				g->level->map[i][j].drawingRect.y = g->level->map[i][j].posRect.y - g->miner.cameraRect.y;
				g->level->map[i][j].drawingRect.w = g->level->map[i][j].posRect.w;
				g->level->map[i][j].drawingRect.h = g->level->map[i][j].posRect.h;
				SDL_RenderCopy(renderer,g->tex,&g->level->map[i][j].cropRect,&g->level->map[i][j].drawingRect);
			}

		if(g->miner.state == ACTIVE)
		{
			g->miner.drawingRect.x = g->miner.posRect.x - g->miner.cameraRect.x;
			g->miner.drawingRect.y = g->miner.posRect.y - g->miner.cameraRect.y;
			g->miner.drawingRect.w = g->miner.posRect.w;
			g->miner.drawingRect.h = g->miner.posRect.h;
			SDL_RenderCopy(renderer,g->miner.tex,&g->miner.cropRect,&g->miner.drawingRect);
		}
		
		SDL_RenderPresent(renderer);

		if(g->miner.cameraRect.y != 0)
			g->miner.cameraRect.y -= 5;
		else
			g->miner.cameraRect.x -= 5;

		SDL_Delay(10);
	}
}
#BD Basis
#include "BD_basis.h"

bool SDL_Initialization()
{
	Uint32 renderer_flag = SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC;

	if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) != 0)
	{
		printf("Error! Initializing : %s\n",SDL_GetError());
		return false;
	}

	if(Mix_OpenAudio(44100,MIX_DEFAULT_FORMAT,2,2048) != 0)
	{
		printf("Error! Mixer could not initialize : %s\n",Mix_GetError());
		return false;
	}

	if(TTF_Init() != 0)
	{
		printf("Error! TTF Initializing : %s\n",TTF_GetError());
		return false;
	}
	
	win = SDL_CreateWindow("Boulder Dash",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,WINDOW_WIDTH,WINDOW_HEIGHT,0);
	if(!win)
	{
		printf("Error! Creating window : %s\n",SDL_GetError());
		SDL_Quit();
		return false;
	}

	renderer = SDL_CreateRenderer(win,-1,renderer_flag);
	if(!renderer)
	{
		printf("Error! Renderering : %s\n",SDL_GetError());
		SDL_DestroyWindow(win);
		SDL_Quit();
		return false;
	}
	SDL_SetRenderDrawColor(renderer,0,0,0,255);
	return true;
}

bool SDL_Load_Texture_Audio_TTF()
{
	SDL_Surface *sur = IMG_Load(IMG_FILE_PATH"/Textures.png");
	if(!sur) return false;
	textures = SDL_CreateTextureFromSurface(renderer,sur);
	SDL_FreeSurface(sur);
	if(!textures) return false;

	SDL_Surface *introSur = IMG_Load(IMG_FILE_PATH"/intro.png");
	if(!introSur) return false;
	introTex = SDL_CreateTextureFromSurface(renderer,introSur);
	SDL_FreeSurface(introSur);
	if(!introTex) return false;

	SDL_Surface *howtoSur = IMG_Load(IMG_FILE_PATH"/howto.png");
	if(!howtoSur) return false;
	howtoTex = SDL_CreateTextureFromSurface(renderer,howtoSur);
	SDL_FreeSurface(howtoSur);
	if(!howtoTex) return false;

	SDL_Surface *finalSur = IMG_Load(IMG_FILE_PATH"/final.png");
	if(!finalSur) return false;
	finalTex = SDL_CreateTextureFromSurface(renderer,finalSur);
	SDL_FreeSurface(finalSur);
	if(!finalTex) return false;

	SDL_Surface *minerSur = IMG_Load(IMG_FILE_PATH"/miner.png");
	if(!minerSur) return false;
	minerTex = SDL_CreateTextureFromSurface(renderer,minerSur);
	SDL_FreeSurface(minerSur);
	if(!minerTex) return false;

	SDL_Surface *panelSur = IMG_Load(IMG_FILE_PATH"/Panel.png");
	if(!panelSur) return false;
	panelTex = SDL_CreateTextureFromSurface(renderer,panelSur);
	SDL_FreeSurface(panelSur);
	if(!panelTex) return false;

	font = TTF_OpenFont(TTF_FILE_PATH"/game.ttf",20);
	if(!font) return false;

	boulder_world_music = Mix_LoadMUS(MUSIC_FILE_PATH"/1-Boulder_World.mp3");
	if(!boulder_world_music) return false;

	ice_world_music = Mix_LoadMUS(MUSIC_FILE_PATH"/2-Ice_World.mp3");
	if(!ice_world_music) return false;

	ocean_world_music = Mix_LoadMUS(MUSIC_FILE_PATH"/3-Ocean_World.mp3");
	if(!ocean_world_music) return false;

	relic_world_music = Mix_LoadMUS(MUSIC_FILE_PATH"/4-Relic_World.mp3");
	if(!relic_world_music) return false;

	sand_world_music = Mix_LoadMUS(MUSIC_FILE_PATH"/5-Sand_World.mp3");
	if(!sand_world_music) return false;

	volcanic_world_music = Mix_LoadMUS(MUSIC_FILE_PATH"/6-Volcanic_World.mp3");
	if(!volcanic_world_music) return false;

	ending_music = Mix_LoadMUS(MUSIC_FILE_PATH"/7-Ending.mp3");
	if(!volcanic_world_music) return false;

	collectDiamondEffect = Mix_LoadWAV(MUSIC_FILE_PATH"/Diamond.wav");
	if(!collectDiamondEffect) return false;

	moveEarthEffect = Mix_LoadWAV(MUSIC_FILE_PATH"/MoveEarth.wav");
	if(!moveEarthEffect) return false;

	moveSpaceEffect = Mix_LoadWAV(MUSIC_FILE_PATH"/MoveSpace.wav");
	if(!moveSpaceEffect) return false;

	rockEffect = Mix_LoadWAV(MUSIC_FILE_PATH"/Rock.wav");
	if(!rockEffect) return false;

	bonusScoreEffect = Mix_LoadWAV(MUSIC_FILE_PATH"/BonusPoints.wav");
	if(!bonusScoreEffect) return false;

	levelUpEffect = Mix_LoadWAV(MUSIC_FILE_PATH"/LevelUp.wav");
	if(!levelUpEffect) return false;

	return true;
}

void Set_Textures(Game *g)
{
	for(int i=0 ; i < g->level->row ; i++)
		for(int j=0 ; j < g->level->column ; j++)
			Set_Object(g,&g->level->map[i][j],g->level->map[i][j].id,g->level->id);
}

void Set_Object(Game *g, Objects *cur_obj, Object name, int level)
{
	cur_obj->frameCounter = 0;
	cur_obj->discharge = g->level->water_discharge;
	cur_obj->movement = false;
	cur_obj->x_vel = cur_obj->y_vel = 0;

	cur_obj->cropRect.w = cur_obj->cropRect.h = 16;
	cur_obj->cropRect.y = (level-1)/2 * 64;
	cur_obj->frameWidth = 1;
	cur_obj->frameHeight = 4;

	switch(name)
	{
		case MINER:
		case EMPTY:
			cur_obj->cropRect.x = 16*2;
			if((level-1)/2 == 0 || (level-1)/2 == 1)
				cur_obj->frameHeight = 1;
			break;
		case EARTH:
			cur_obj->cropRect.x = 16*1;
			if((level-1)/2 == 0 || (level-1)/2 == 1 || (level-1)/2 == 3)
				cur_obj->frameHeight = 1;
			break;
		case BORDER:
			cur_obj->cropRect.x = 16*0;
			cur_obj->frameHeight = 1;
			break;
		case ROCK:
			cur_obj->cropRect.x = 16*3;
			if((level-1)/2 == 4)
				cur_obj->frameHeight = 1;
			break;
		case DIAMOND:
			cur_obj->cropRect.x = 16*4;
			break;
		case SPIDER:
			cur_obj->cropRect.x = 16*10;
			break;
		case MONSTER:
			cur_obj->cropRect.x = 16*9;
			break;					
		case WATER:
			cur_obj->cropRect.x = 16*7;
			break;
		case DOOR:
			cur_obj->state = PASSIVE;
			cur_obj->cropRect.x = 16*6;
			break;	
	}
}

void Set_Music(Game *g)
{
	if(g->level->id >= 0 && g->level->id <= 2)
		cur_music = boulder_world_music;
	else if(g->level->id >= 3 && g->level->id <= 4)
		cur_music = ice_world_music;
	else if(g->level->id >= 5 && g->level->id <= 6)
		cur_music = ocean_world_music;
	else if(g->level->id >= 7 && g->level->id <= 8)
		cur_music = relic_world_music;
	else if(g->level->id >= 9 && g->level->id <= 10)
		cur_music = sand_world_music;
	else if(g->level->id >= 11 && g->level->id <= 12)
		cur_music = volcanic_world_music;

	Mix_PlayMusic(cur_music,-1);
	Mix_Volume(-1,2*MUSIC_VOL);
	Mix_VolumeMusic(MUSIC_VOL);
}

bool Import_Levels(Game *g)
{
	FILE *fp;
	Level *iter_level;
	Objects *cur_obj;
	int i,j;
	char buffer[255];

	fp = fopen(LEVEL_FILE_PATH"/level.txt","r");
	if(!fp) return false;

	g->level = (Level*)malloc(sizeof(Level));
	g->level->next = NULL;
	iter_level = g->level;

	while(!feof(fp))
	{
		while(str_cmp(buffer,"#level#\n") != 0)
			fgets(buffer,255,fp);
		
		fscanf(fp,"%s%d",buffer,&iter_level->id);
		fscanf(fp,"%s%d",buffer,&iter_level->row);
		fscanf(fp,"%s%d",buffer,&iter_level->column);
		fscanf(fp,"%s%d",buffer,&iter_level->totalDiamond);
		fscanf(fp,"%s%u",buffer,&iter_level->totalTime);
		fscanf(fp,"%s%u",buffer,&iter_level->water_discharge);

		iter_level->map = (Objects**)calloc(iter_level->row,sizeof(Objects*));
		for(i=0 ; i < iter_level->row ; i++)
			iter_level->map[i] = (Objects*)calloc(iter_level->column,sizeof(Objects));

		while(str_cmp(buffer,"#map#\n") != 0)
			fgets(buffer,255,fp);

		for(i=0 ; i < iter_level->row ; i++)
		{
			fgets(buffer,255,fp);
			for(j=0 ; j < iter_level->column ; j++)
			{
				cur_obj = &iter_level->map[i][j];
				cur_obj->id = buffer[j];
				cur_obj->posRect.x = j * CELL_SIZE;
				cur_obj->posRect.y = i * CELL_SIZE;
				cur_obj->posRect.w = cur_obj->posRect.h = CELL_SIZE;
			}
		}

		while(str_cmp(buffer,"#level#\n") != 0 && !feof(fp))
			fgets(buffer,255,fp);

		if(!feof(fp))
		{	
			iter_level->next = (Level*)malloc(sizeof(Level));
			iter_level = iter_level->next;
			iter_level->next = NULL;
		}
	}
	fclose(fp);
	return true;
}

void Level_Again(Game *g, int level_id)
{
	Objects *cur_obj;
	FILE *fp;
	char search[10],buffer[255];
	int i,j;

	g->state = CONTINUE;
	g->miner.health--;
	g->miner.collectedDiamond = 0;
	g->miner.elapsedTime = 0;
	sprintf(search,"ID= %d\n",level_id);

	fp = fopen(LEVEL_FILE_PATH"/level.txt","r");

	while(str_cmp(search,buffer) != 0)
		fgets(buffer,255,fp);
	while(str_cmp(buffer,"#map#\n") != 0)
		fgets(buffer,255,fp);

	for(i=0 ; i < g->level->row ; ++i)
		free(g->level->map[i]);
	free(g->level->map);

	g->level->map = (Objects**)calloc(g->level->row,sizeof(Objects*));
	for(i=0 ; i < g->level->row ; ++i)
		g->level->map[i] = (Objects*)calloc(g->level->column,sizeof(Objects));

	for(i=0 ; i < g->level->row ; ++i)
	{
		fgets(buffer,255,fp);
		for(j=0 ; j < g->level->column ; ++j)
		{
			cur_obj = &g->level->map[i][j];
			cur_obj->id = buffer[j];
			cur_obj->posRect.x = j * CELL_SIZE;
			cur_obj->posRect.y = i * CELL_SIZE;
			cur_obj->posRect.w = cur_obj->posRect.h = CELL_SIZE;
		}
	}
	fclose(fp);

	Set_Textures(g);
}

void Free_Level(Level *cur)
{
	if(cur != NULL)
	{
		if(cur->next != NULL)
			Free_Level(cur->next);

		for(int i=0 ; i< cur->row ; i++)
			free(cur->map[i]);
		free(cur->map);
		free(cur);
	}
}

void SDL_DestroyTextures_And_Quit(Game *g)
{
	SDL_DestroyTexture(textures);
	SDL_DestroyTexture(introTex);
	SDL_DestroyTexture(howtoTex);
	SDL_DestroyTexture(finalTex);
	SDL_DestroyTexture(minerTex);
	SDL_DestroyTexture(panelTex);
	if(!g->panel.textScore)
	{
		SDL_DestroyTexture(g->panel.textHealth);
		SDL_DestroyTexture(g->panel.textLevel);
		SDL_DestroyTexture(g->panel.textDia);
		SDL_DestroyTexture(g->panel.textTime);
		SDL_DestroyTexture(g->panel.textScore);
	}
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(win);
	TTF_CloseFont(font);
	TTF_Quit();
	Mix_FreeChunk(collectDiamondEffect);
	Mix_FreeChunk(moveEarthEffect);
	Mix_FreeChunk(moveSpaceEffect);
	Mix_FreeChunk(rockEffect);
	Mix_FreeChunk(bonusScoreEffect);
	Mix_FreeChunk(levelUpEffect);
	Mix_FreeMusic(boulder_world_music);
	Mix_FreeMusic(ice_world_music);
	Mix_FreeMusic(ocean_world_music);
	Mix_FreeMusic(relic_world_music);
	Mix_FreeMusic(sand_world_music);
	Mix_FreeMusic(volcanic_world_music);
	Mix_FreeMusic(ending_music);
	Mix_Quit();
	SDL_Quit();
	Free_Level(g->level);
}

int str_cmp(char *s1, char *s2)
{
	while(*s1 && *s2 && *s1 == *s2)
		s1++,s2++;
	return *s1 - *s2;
}
# Game_C
#include "BD_game.h"

void Game_Initialization(Game *g)
{
	g->state = LEVELUP;
	g->tex = textures;
	g->panel.tex = panelTex;

	g->panel.cropScore.x = g->panel.cropTime.x = g->panel.cropDia.x = g->panel.cropLevel.x = g->panel.cropHealth.x = 0;
	g->panel.cropScore.y = 0,g->panel.cropTime.y = 46,g->panel.cropDia.y = 46*2,g->panel.cropLevel.y = 46*3,g->panel.cropHealth.y = 46*4;
	g->panel.cropScore.w = 242,g->panel.cropTime.w = 152,g->panel.cropDia.w = g->panel.cropLevel.w = g->panel.cropHealth.w = 120;
	g->panel.cropScore.h = g->panel.cropTime.h = g->panel.cropDia.h = g->panel.cropLevel.h = g->panel.cropHealth.h = 46;
	g->panel.posScore.x = 25*WINDOW_WIDTH/40,g->panel.posTime.x = 10*WINDOW_WIDTH/20,g->panel.posDia.x = 8*WINDOW_WIDTH/20,g->panel.posLevel.x = 6*WINDOW_WIDTH/20,g->panel.posHealth.x = 4*WINDOW_WIDTH/20;
	g->panel.posScore.y = g->panel.posTime.y = g->panel.posDia.y = g->panel.posLevel.y = g->panel.posHealth.y = 100*WINDOW_HEIGHT/5065;
	g->panel.posScore.w = 10*WINDOW_WIDTH/53,g->panel.posTime.w = 10*WINDOW_WIDTH/84,g->panel.posDia.w = g->panel.posLevel.w = g->panel.posHealth.w = 100*WINDOW_WIDTH/1065;	
	g->panel.posScore.h = g->panel.posTime.h = g->panel.posDia.h = g->panel.posLevel.h = g->panel.posHealth.h = 10*WINDOW_HEIGHT/165;	
	g->panel.posTextScore.x = 103*WINDOW_WIDTH/160,g->panel.posTextTime.x = 85*WINDOW_WIDTH/160,g->panel.posTextDia.x = 69*WINDOW_WIDTH/160,g->panel.posTextLevel.x = 54*WINDOW_WIDTH/160,g->panel.posTextHealth.x = 37*WINDOW_WIDTH/160;
	g->panel.posTextScore.y = g->panel.posTextTime.y = g->panel.posTextDia.y = g->panel.posTextLevel.y = g->panel.posTextHealth.y = 0;
	g->panel.posTextScore.w = 6*WINDOW_WIDTH/40,g->panel.posTextTime.w = 3*WINDOW_WIDTH/40,g->panel.posTextDia.w = g->panel.posTextLevel.w = g->panel.posTextHealth.w = 2*WINDOW_WIDTH/40;
	g->panel.posTextScore.h = g->panel.posTextTime.h = g->panel.posTextDia.h = g->panel.posTextLevel.h = g->panel.posTextHealth.h = 1000*WINDOW_HEIGHT/11875;
	g->panel.c.r = g->panel.c.g = g->panel.c.b = g->panel.c.a = 255;
	g->panel.cur_level = 0 , g->panel.score = 0;

	g->miner.tex = minerTex;
	SDL_QueryTexture(g->miner.tex,NULL,NULL,&g->miner.textureWidth,&g->miner.textureHeight);
	g->miner.frameWidth = 3 , g->miner.frameHeight = 4;
	g->miner.cropRect.w = g->miner.textureWidth / g->miner.frameWidth;
	g->miner.cropRect.h = g->miner.textureHeight / g->miner.frameHeight;
	g->miner.cropRect.x = g->miner.cropRect.w , g->miner.cropRect.y = 0;
	g->miner.posRect.x = g->miner.posRect.y = 0;
	g->miner.posRect.w = g->miner.posRect.h = CELL_SIZE;
	g->miner.cameraRect.x = g->miner.cameraRect.y = 0;
	g->miner.cameraRect.w = WINDOW_WIDTH;
	g->miner.cameraRect.h = WINDOW_HEIGHT;
	g->miner.keys[0] = SDL_SCANCODE_UP;
	g->miner.keys[1] = SDL_SCANCODE_DOWN;
	g->miner.keys[2] = SDL_SCANCODE_RIGHT;
	g->miner.keys[3] = SDL_SCANCODE_LEFT;
	g->miner.frameCounter = 0;
	g->miner.x_vel = g->miner.y_vel = 0;
	g->miner.collectedDiamond = 0;
	g->miner.movement = false;
	g->miner.health = 10;
	g->miner.state = ACTIVE;
	g->miner.elapsedTime = g->miner.prevTime = g->miner.curTime = 0;
}

void Get_Event(Game *g)
{
	while(SDL_PollEvent(&event))
	{
		switch(event.type)
		{
			case SDL_QUIT:
				g->state = FINISH;
				break;
			case SDL_KEYDOWN:
			{
				switch(event.key.keysym.scancode)
				{
					case SDL_SCANCODE_ESCAPE:
						g->state = FINISH;
						break;
					case SDL_SCANCODE_P:
						if(g->state == CONTINUE)
						{
							g->state = PAUSE;
							Mix_PauseMusic();
						}
						else
						{
							g->state = CONTINUE;
							Mix_ResumeMusic();
						}
						break;
					case SDL_SCANCODE_R:
						g->state = LEVELAGAIN;
						break;
					case SDL_SCANCODE_M:
						if(Mix_PausedMusic())
							Mix_ResumeMusic();
						else
							Mix_PauseMusic();
						break;
					case SDL_SCANCODE_F1:
						g->state = CHEAT;
						break;
					default:
						break;
				}
			}
		}
	}
}

void Update_Miner(Game *g)
{
	Objects temp;
	const Uint8 *keyState;
	int i,j,x,y;

	g->miner.movement = true;
	g->miner.frameCounter++;

	keyState = SDL_GetKeyboardState(NULL);

	if(keyState[g->miner.keys[0]])
	{
		g->miner.x_vel = 0 , g->miner.y_vel = -CELL_SIZE;
		g->miner.cropRect.y = g->miner.cropRect.h * 3;
	}
	else if(keyState[g->miner.keys[1]])
	{
		g->miner.x_vel = 0 , g->miner.y_vel = CELL_SIZE;
		g->miner.cropRect.y = 0;
	}
	else if(keyState[g->miner.keys[2]])
	{
		g->miner.x_vel = CELL_SIZE , g->miner.y_vel = 0;
		g->miner.cropRect.y = g->miner.cropRect.h * 2;
	}
	else if(keyState[g->miner.keys[3]])
	{
		g->miner.x_vel = -CELL_SIZE , g->miner.y_vel = 0;
		g->miner.cropRect.y = g->miner.cropRect.h;
	}
	else
	{
		g->miner.x_vel = 0 , g->miner.y_vel = 0;
		g->miner.movement = false;
	}

	i = g->miner.posRect.x/CELL_SIZE;
	x = g->miner.x_vel/CELL_SIZE;
	j = g->miner.posRect.y/CELL_SIZE;
	y = g->miner.y_vel/CELL_SIZE;

	if(g->miner.movement && g->miner.frameCounter >= FPS/MINER_SPEED)
	{
		g->miner.frameCounter = 0;
		g->miner.cropRect.x += g->miner.cropRect.w;
		if(g->miner.cropRect.x >= g->miner.textureWidth)
			g->miner.cropRect.x = 0;

		switch(g->level->map[j+y][i+x].id)
		{
			case EARTH:
				temp = g->level->map[j][i];
				g->level->map[j][i] = g->level->map[j+y][i+x];
				g->level->map[j+y][i+x] = temp;

				g->level->map[j][i].id = EMPTY;
				Set_Object(g,&g->level->map[j][i],g->level->map[j][i].id,g->level->id);
				g->level->map[j][i].posRect.x -= g->miner.x_vel , g->level->map[j][i].posRect.y -= g->miner.y_vel;

				g->level->map[j+y][i+x].posRect.x += g->miner.x_vel , g->level->map[j+y][i+x].posRect.y += g->miner.y_vel;
				g->miner.posRect.x += g->miner.x_vel , g->miner.posRect.y += g->miner.y_vel;
				Mix_PlayChannel(-1,moveEarthEffect,0);
				break;
			case EMPTY:
				temp = g->level->map[j][i];
				g->level->map[j][i] = g->level->map[j+y][i+x];
				g->level->map[j+y][i+x] = temp;

				g->level->map[j][i].posRect.x -= g->miner.x_vel , g->level->map[j][i].posRect.y -= g->miner.y_vel;
				g->level->map[j+y][i+x].posRect.x += g->miner.x_vel , g->level->map[j+y][i+x].posRect.y += g->miner.y_vel;
				g->miner.posRect.x += g->miner.x_vel , g->miner.posRect.y += g->miner.y_vel;
				Mix_PlayChannel(-1,moveSpaceEffect,0);
				break;
			case ROCK:
				if(g->miner.x_vel > 0 && g->level->map[j+y][i+x+1].id == EMPTY)
				{
					temp = g->level->map[j+y][i+x+1];
					g->level->map[j+y][i+x+1] = g->level->map[j+y][i+x];
					g->level->map[j+y][i+x] = temp;

					g->level->map[j+y][i+x+1].posRect.x += CELL_SIZE;
					g->level->map[j+y][i+x].posRect.x -= CELL_SIZE;
				}
				else if(g->miner.x_vel < 0 && g->level->map[j+y][i+x-1].id == EMPTY)
				{
					temp = g->level->map[j+y][i+x-1];
					g->level->map[j+y][i+x-1] = g->level->map[j+y][i+x];
					g->level->map[j+y][i+x] = temp;

					g->level->map[j+y][i+x-1].posRect.x -= CELL_SIZE;
					g->level->map[j+y][i+x].posRect.x += CELL_SIZE;
				}
				break;
			case DIAMOND:
				temp = g->level->map[j][i];
				g->level->map[j][i] = g->level->map[j+y][i+x];
				g->level->map[j+y][i+x] = temp;

				g->level->map[j][i].id = EMPTY;
				Set_Object(g,&g->level->map[j][i],g->level->map[j][i].id,g->level->id);
				g->level->map[j][i].posRect.x -= g->miner.x_vel , g->level->map[j][i].posRect.y -= g->miner.y_vel;

				g->level->map[j+y][i+x].posRect.x += g->miner.x_vel , g->level->map[j+y][i+x].posRect.y += g->miner.y_vel;
				g->miner.posRect.x += g->miner.x_vel , g->miner.posRect.y += g->miner.y_vel;

				g->panel.score += 20;
				g->miner.collectedDiamond++;
				Mix_PlayChannel(-1,collectDiamondEffect,0);
				break;
			case DOOR:
				if(g->miner.collectedDiamond >= g->level->totalDiamond)
				{
					g->miner.posRect.x += g->miner.x_vel;
					g->miner.posRect.y += g->miner.y_vel;
					g->state = LEVELUP;
					Mix_PlayChannel(-1,levelUpEffect,0);
					Level_Final(g);
				}
				break;
			default:
				break;
		}
	}
	else if(g->miner.frameCounter >= FPS/MINER_SPEED)
	{
		g->miner.frameCounter = 0;
		g->miner.cropRect.x = g->miner.cropRect.w;
		g->miner.cropRect.y = 0;
	}

	g->miner.cameraRect.x = g->miner.posRect.x - WINDOW_WIDTH/2;
	g->miner.cameraRect.y = g->miner.posRect.y - WINDOW_HEIGHT/2;

	if(g->miner.cameraRect.x < 0)
		g->miner.cameraRect.x = 0;
	if(g->miner.cameraRect.y < 0)
		g->miner.cameraRect.y = 0;
	if(g->miner.cameraRect.x + g->miner.cameraRect.w >= g->level->column * CELL_SIZE)
		g->miner.cameraRect.x = g->level->column * CELL_SIZE - WINDOW_WIDTH;
	if(g->miner.cameraRect.y + g->miner.cameraRect.h >= g->level->row * CELL_SIZE)
		g->miner.cameraRect.y = g->level->row * CELL_SIZE - WINDOW_HEIGHT;
}

void Update_Objects(Game *g)
{
	int i,j;
	bool alive = true;

	for(i=0; i < g->level->row ; ++i)
		for(j=0; j< g->level->column ; ++j)
			g->level->map[i][j].update = true;

	for(i=0 ; i < g->level->row ; ++i)
	{
		for(j=0; j < g->level->column ; ++j)
		{
			if(g->level->map[i][j].update == true)
				switch(g->level->map[i][j].id)
				{
					case EMPTY:
						Update_Empty(g,i,j);
						break;
					case EARTH:
						Update_Earth(g,i,j);
						break;
					case ROCK:
						alive = Update_Rock(g,i,j);
						break;
					case DIAMOND:
						Update_Diamond(g,i,j);
						break;
					case WATER:
						Update_Water(g,i,j);
						break;
					case DOOR:
						Update_Door(g,i,j);
						break;
					case SPIDER:
						alive = Update_Spider(g,i,j);
						break;
					case MONSTER:
						alive = Update_Monster(g,i,j);
						break;
					default:
						break;
				}
			if(alive == false)
			{
				g->state = LEVELAGAIN;
				return;
			}
		}
	}
}

void Swap_Objects(Objects *obj1, Objects *obj2)
{
	Objects temp;
	SDL_Rect position;

	position = obj1->posRect;
	obj1->posRect = obj2->posRect;
	obj2->posRect = position;

	temp= *obj1;
	*obj1 = *obj2;
	*obj2 = temp;
}

void Update_Texture(Game *g, int row, int column)
{
	g->level->map[row][column].cropRect.y += g->level->map[row][column].cropRect.h;
	if(g->level->map[row][column].cropRect.y >= (g->level->id-1)/2 * 64 + g->level->map[row][column].cropRect.h * g->level->map[row][column].frameHeight)
		g->level->map[row][column].cropRect.y = (g->level->id-1)/2 * 64;
}

void Update_Empty(Game *g, int row, int column)
{
	g->level->map[row][column].update = false;
	g->level->map[row][column].frameCounter++;
	if(g->level->map[row][column].frameCounter >= (FPS/OBJ_UPDATE_SPEED))
	{
		g->level->map[row][column].frameCounter = 0;
		Update_Texture(g,row,column);
	}
}

void Update_Earth(Game *g, int row, int column)
{
	g->level->map[row][column].update = false;
	g->level->map[row][column].frameCounter++;
	if(g->level->map[row][column].frameCounter >= (FPS/OBJ_UPDATE_SPEED))
	{
		g->level->map[row][column].frameCounter = 0;
		Update_Texture(g,row,column);
	}
}

bool Update_Rock(Game *g, int row, int column)
{
	g->level->map[row][column].update = false;
	g->level->map[row][column].frameCounter++;

	if(g->level->map[row][column].frameCounter >= FPS/ROCK_FALL_SPEED)
	{
		if(g->level->map[row][column].state == ROLL)
		{
			if(g->level->map[row+1][column].id != EMPTY)
				Mix_PlayChannel(-1,rockEffect,0);
			switch(g->level->map[row+1][column].id)
			{
				case MINER:
					return false;
				case SPIDER:
					g->level->map[row+1][column].id = EMPTY;
					Set_Object(g,&g->level->map[row+1][column],g->level->map[row+1][column].id,g->level->id);
					Turn_To_Diamond(g,row+1,column,8);
					break;
				case MONSTER:
					g->level->map[row+1][column].id = EMPTY;
					Set_Object(g,&g->level->map[row+1][column],g->level->map[row+1][column].id,g->level->id);
					Turn_To_Diamond(g,row+1,column,12);
					break;
				default:
					break;
			}
		}

		if(g->level->map[row+1][column].id == EMPTY)
			g->level->map[row][column].state = ROLL;
		else
			g->level->map[row][column].state = ACTIVE;
	}

	if(g->level->map[row][column].frameCounter % (FPS/OBJ_UPDATE_SPEED) == 0)
		Update_Texture(g,row,column);

	if(g->level->map[row][column].frameCounter >= (FPS/ROCK_FALL_SPEED))
	{
		g->level->map[row][column].frameCounter = 0;

		if(g->level->map[row+1][column].id == EMPTY)
			Swap_Objects(&g->level->map[row][column],&g->level->map[row+1][column]);
		else if(g->level->map[row+1][column].id == ROCK && g->level->map[row][column-1].id == EMPTY && g->level->map[row+1][column-1].id == EMPTY)
			Swap_Objects(&g->level->map[row][column],&g->level->map[row][column-1]);
		else if(g->level->map[row+1][column].id == ROCK && g->level->map[row][column+1].id == EMPTY && g->level->map[row+1][column+1].id == EMPTY)
			Swap_Objects(&g->level->map[row][column],&g->level->map[row][column+1]);
	}
	return true;
}

void Update_Diamond(Game *g, int row, int column)
{
	g->level->map[row][column].update = false;
	g->level->map[row][column].frameCounter++;

	if(g->level->map[row][column].frameCounter % (FPS/OBJ_UPDATE_SPEED) == 0)
		Update_Texture(g,row,column);

	if(g->level->map[row][column].frameCounter >= (FPS/DIA_FALL_SPEED))
	{
		g->level->map[row][column].frameCounter = 0;

		if(g->level->map[row+1][column].id == EMPTY)
			Swap_Objects(&g->level->map[row][column],&g->level->map[row+1][column]);
		else if(g->level->map[row+1][column].id == DIAMOND && g->level->map[row][column-1].id == EMPTY && g->level->map[row+1][column-1].id == EMPTY)
			Swap_Objects(&g->level->map[row][column],&g->level->map[row][column-1]);
		else if(g->level->map[row+1][column].id == DIAMOND && g->level->map[row][column+1].id == EMPTY && g->level->map[row+1][column+1].id == EMPTY)
			Swap_Objects(&g->level->map[row][column],&g->level->map[row][column+1]);
	}
}

bool Update_Spider(Game *g, int row, int column)
{
	int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
	int i,j;

	g->level->map[row][column].update = false;
	g->level->map[row][column].frameCounter++;

	if(g->level->map[row+1][column].id == MINER || g->level->map[row-1][column].id == MINER ||
		g->level->map[row][column+1].id == MINER || g->level->map[row][column-1].id == MINER)
		return false;

	if(g->level->map[row][column].frameCounter % (FPS/OBJ_UPDATE_SPEED) == 0)
		Update_Texture(g,row,column);

	if(g->level->map[row][column].frameCounter >= (FPS/SPIDER_SPEED))
	{
		g->level->map[row][column].frameCounter = 0;
		if(g->level->map[row+1][column].id != EMPTY &&
		   g->level->map[row-1][column].id != EMPTY &&
		   g->level->map[row][column+1].id != EMPTY &&
		   g->level->map[row][column-1].id != EMPTY)
			g->level->map[row][column].x_vel = g->level->map[row][column].y_vel = 0;
		else
		{
			g->level->map[row][column].x_vel *= -1;
			g->level->map[row][column].y_vel *= -1;

			for(i=0;i<4;i++)
				if(dir[i][0] == g->level->map[row][column].y_vel && dir[i][1] == g->level->map[row][column].x_vel)
					break;
			for(j=1;j<=4;j++)
			{
				i++;
				if(i > 3) i=0;
				if(g->level->map[row + dir[i][0]][column + dir[i][1]].id == ROCK && g->level->map[row + dir[i][0]][column + dir[i][1]].state == ROLL)
				{
					g->level->map[row][column].x_vel = g->level->map[row][column].y_vel = 0;
					break;
				}
				else if(g->level->map[row + dir[i][0]][column + dir[i][1]].id == EMPTY)
				{
					g->level->map[row][column].x_vel = dir[i][1];
					g->level->map[row][column].y_vel = dir[i][0];
					break;
				}
			}
		}

		Swap_Objects(&g->level->map[row][column],&g->level->map[row + g->level->map[row][column].y_vel][column + g->level->map[row][column].x_vel]);
	}
	return true;
}

bool Update_Monster(Game *g, int row, int column)
{
	int m_x,m_y,x=0,y=0;
	int count1 = 0,count2 = 0;

	g->level->map[row][column].update = false;
	g->level->map[row][column].frameCounter++;

	if(g->level->map[row+1][column].id == MINER || g->level->map[row-1][column].id == MINER ||
		g->level->map[row][column+1].id == MINER || g->level->map[row][column-1].id == MINER)
		return false;

	if(g->level->map[row][column].frameCounter % (FPS/OBJ_UPDATE_SPEED) == 0)
		Update_Texture(g,row,column);

	if(g->level->map[row][column].frameCounter >= (FPS/MONSTER_SPEED))
	{
		g->level->map[row][column].frameCounter = 0;
		m_x = g->miner.posRect.x / CELL_SIZE;
		m_y = g->miner.posRect.y / CELL_SIZE;

		if(m_x - column > 0 && m_y - row > 0)
			x = y = 1;
		else if(m_x - column > 0 && m_y - row < 0)
			x = 1 , y = -1;
		else if(m_x - column < 0 && m_y - row > 0)
			x = -1 , y = 1;
		else if(m_x - column < 0 && m_y - row < 0)
			x = y = -1;
		else if(m_x - column == 0 && m_y - row > 0)
			x = 0 , y = 1;
		else if(m_x - column == 0 && m_y - row < 0)
			x = 0 , y = -1;
		else if(m_x - column > 0 && m_y - row == 0)
			x = 1 , y = 0;
		else if(m_x - column < 0 && m_y - row == 0)
			x = -1 , y = 0;

		count1 = Monster_Path(g,row,column+x,x,y);
		count2 = Monster_Path(g,row+y,column,x,y);

		if(count1 == 0 && count2 == 0)
			x = y = 0;
		else if(count1 >= count2)
			y = 0;
		else if(count1 < count2)
			x = 0;

		if(x || y)
			Swap_Objects(&g->level->map[row][column],&g->level->map[row + y][column + x]);
	}
	return true;
}

int Monster_Path(Game *g, int row, int column, int x, int y)
{
	int way1=0,way2=0;
	if (g->level->map[row][column].id != EMPTY)  
		return 0;
	else
	{
		if(y != 0)
			way1 = Monster_Path(g,row+y,column,x,y);
		if(x != 0)
			way2 = Monster_Path(g,row,column+x,x,y);
		if(way1 > way2)
			return(way1+1);
		else
			return(way2+1);
	}
}

void Update_Water(Game *g, int row, int column)
{
	int arr[WATER_MAX_SIZE][2];
	int i,j,r,size=1;

	for(i=0 ; i < WATER_MAX_SIZE ; i++)
		for(j=0 ; j < 2 ; j++)
			arr[i][j] = -1;

	g->level->map[row][column].discharge -= g->miner.curTime - g->miner.prevTime;

	Find_EmptyCell(g,row,column,arr,size);

	if(size < WATER_MAX_SIZE && (int)g->level->map[row][column].discharge <= 0)
	{
		g->level->map[row][column].discharge = g->level->water_discharge;

		for(i=0 ; i < WATER_MAX_SIZE ; i++)
			if(arr[i][0] == -1)
				break;
		if(i != 0)
		{
			r = rand()%i;
			g->level->map[arr[r][0]][arr[r][1]].id = WATER;
			Set_Object(g,&g->level->map[arr[r][0]][arr[r][1]],WATER,g->level->id);
		}
		else
			Turn_Water_Into_Diamond(g,row,column);
	}
}

void Find_EmptyCell(Game *g, int row, int column,int arr[][2], int size)
{
	int i,j;

	g->level->map[row][column].update = false;
	g->level->map[row][column].frameCounter++;

	if(g->level->map[row][column].frameCounter >= (FPS/OBJ_UPDATE_SPEED))
	{
		g->level->map[row][column].frameCounter = 0;
		Update_Texture(g,row,column);
	}

	if(g->level->map[row-1][column].id == WATER && g->level->map[row-1][column].update == true)
		Find_EmptyCell(g,row-1,column,arr,++size);
	else if(g->level->map[row-1][column].id != WATER && size < WATER_MAX_SIZE && (g->level->map[row-1][column].id == EMPTY || g->level->map[row-1][column].id == EARTH))
	{
		for(i=0 ; i < WATER_MAX_SIZE ; i++)
			if(arr[i][0] == -1)
				break;
		for(j=0 ; j <= i ; j++)
			if(arr[j][0] == row-1 && arr[j][1] == column)
			{
				i = -1;
				break;
			}
		if(i != -1)
			arr[i][0] = row-1 , arr[i][1] = column;
	}

	if(g->level->map[row][column-1].id == WATER && g->level->map[row][column-1].update == true)
		Find_EmptyCell(g,row,column-1,arr,++size);
	else if(g->level->map[row][column-1].id != WATER && size < WATER_MAX_SIZE && (g->level->map[row][column-1].id == EMPTY || g->level->map[row][column-1].id == EARTH))
	{
		for(i=0 ; i < WATER_MAX_SIZE ; i++)
			if(arr[i][0] == -1)
				break;
		for(j=0 ; j <= i ; j++)
			if(arr[j][0] == row && arr[j][1] == column-1)
			{
				i = -1;
				break;
			}
		if(i != -1)
			arr[i][0] = row , arr[i][1] = column-1;
	}

	if(g->level->map[row][column+1].id == WATER && g->level->map[row][column+1].update == true)
		Find_EmptyCell(g,row,column+1,arr,++size);
	else if(g->level->map[row][column+1].id != WATER && size < WATER_MAX_SIZE && (g->level->map[row][column+1].id == EMPTY || g->level->map[row][column+1].id == EARTH))
	{
		for(i=0 ; i < WATER_MAX_SIZE ; i++)
			if(arr[i][0] == -1)
				break;
		for(j=0 ; j <= i ; j++)
			if(arr[j][0] == row && arr[j][1] == column+1)
			{
				i = -1;
				break;
			}
		if(i != -1)
			arr[i][0] = row , arr[i][1] = column+1;
	}

	if(g->level->map[row+1][column].id == WATER && g->level->map[row+1][column].update == true)
		Find_EmptyCell(g,row+1,column,arr,++size);
	else if(g->level->map[row+1][column].id != WATER && size < WATER_MAX_SIZE && (g->level->map[row+1][column].id == EMPTY || g->level->map[row+1][column].id == EARTH))
	{
		for(i=0 ; i < WATER_MAX_SIZE ; i++)
			if(arr[i][0] == -1)
				break;
		for(j=0 ; j <= i ; j++)
			if(arr[j][0] == row+1 && arr[j][1] == column)
			{
				i = -1;
				break;
			}
		if(i != -1)
			arr[i][0] = row+1 , arr[i][1] = column;
	}
}

void Turn_Water_Into_Diamond(Game *g, int row, int column)
{
	g->level->map[row][column].id = DIAMOND;
	Set_Object(g,&g->level->map[row][column],DIAMOND,g->level->id);
	
	if(g->level->map[row-1][column].id == WATER)
		Turn_Water_Into_Diamond(g,row-1,column);
	if(g->level->map[row][column-1].id == WATER)
		Turn_Water_Into_Diamond(g,row,column-1);
	if(g->level->map[row][column+1].id == WATER)
		Turn_Water_Into_Diamond(g,row,column+1);
	if(g->level->map[row+1][column].id == WATER)
		Turn_Water_Into_Diamond(g,row+1,column);
}

void Update_Door(Game *g, int row, int column)
{
	g->level->map[row][column].frameCounter++;

	if(g->miner.collectedDiamond < g->level->totalDiamond)
		Set_Object(g,&g->level->map[row][column],BORDER,g->level->id);
	else if(g->level->map[row][column].state == PASSIVE)
	{
		Set_Object(g,&g->level->map[row][column],DOOR,g->level->id);
		g->level->map[row][column].state = ACTIVE;
	}

	if(g->miner.collectedDiamond >= g->level->totalDiamond && g->level->map[row][column].frameCounter >= (FPS/OBJ_UPDATE_SPEED))
	{
		g->level->map[row][column].frameCounter = 0;
		Update_Texture(g,row,column);
	}
}

void Update_Score_Level(Game *g)
{
	char health_buffer[3],level_buffer[3],dia_buffer[3],time_buffer[4],score_buffer[7];

	sprintf(health_buffer,"%02d",g->miner.health);
	sprintf(level_buffer,"%02d",g->panel.cur_level);
	if(g->level->totalDiamond - g->miner.collectedDiamond < 0)
		sprintf(dia_buffer,"%02d",0);
	else
		sprintf(dia_buffer,"%02d",g->level->totalDiamond - g->miner.collectedDiamond);

	if((int)(g->level->totalTime - g->miner.elapsedTime) < 0)
		sprintf(time_buffer,"%03d",0);
	else
		sprintf(time_buffer,"%03d",(g->level->totalTime - g->miner.elapsedTime)/1000);
	sprintf(score_buffer,"%06d",g->panel.score);

	if(!g->panel.textScore)
	{
		SDL_DestroyTexture(g->panel.textHealth);
		SDL_DestroyTexture(g->panel.textLevel);
		SDL_DestroyTexture(g->panel.textDia);
		SDL_DestroyTexture(g->panel.textTime);
		SDL_DestroyTexture(g->panel.textScore);
	}
	
	SDL_Surface *textHealthSur = TTF_RenderText_Solid(font,health_buffer,g->panel.c);
	g->panel.textHealth = SDL_CreateTextureFromSurface(renderer,textHealthSur);
	SDL_FreeSurface(textHealthSur);

	SDL_Surface *textLevelSur = TTF_RenderText_Solid(font,level_buffer,g->panel.c);
	g->panel.textLevel = SDL_CreateTextureFromSurface(renderer,textLevelSur);
	SDL_FreeSurface(textLevelSur);

	SDL_Surface *textDiaSur = TTF_RenderText_Solid(font,dia_buffer,g->panel.c);
	g->panel.textDia = SDL_CreateTextureFromSurface(renderer,textDiaSur);
	SDL_FreeSurface(textDiaSur);

	SDL_Surface *textTimeSur = TTF_RenderText_Solid(font,time_buffer,g->panel.c);
	g->panel.textTime = SDL_CreateTextureFromSurface(renderer,textTimeSur);
	SDL_FreeSurface(textTimeSur);

	SDL_Surface *textScoreSur = TTF_RenderText_Solid(font,score_buffer,g->panel.c);
	g->panel.textScore = SDL_CreateTextureFromSurface(renderer,textScoreSur);
	SDL_FreeSurface(textScoreSur);
}

void Turn_To_Diamond(Game *g, int row, int column, int dia)
{
	int i,j,count=0;

	for(i = row-1 ; i <= row-1+dia/3; ++i)
		for(j = column-1 ; j <= column+1 ; ++j)
		{
			if((g->level->map[i][j].id == EMPTY || g->level->map[i][j].id == EARTH) && count <= dia)
			{
				g->level->map[i][j].id = DIAMOND;
				Set_Object(g,&g->level->map[i][j],g->level->map[i][j].id,g->level->id);
			}
			count++;
		}
}

void Cheat_Game(Game *g)
{
	char text[64] = {'\0'};
	int i;
	SDL_StartTextInput();

	while(g->state == CHEAT)
	{
		while(SDL_PollEvent(&event))
		{
			switch(event.type)
			{
				case SDL_QUIT:
					g->state = FINISH;
					break;
				case SDL_KEYDOWN:
					switch(event.key.keysym.scancode)
					{
						case SDL_SCANCODE_F1:
							g->state = CONTINUE;
							break;
						case SDL_SCANCODE_ESCAPE:
							g->state = FINISH;
							break;
						case SDL_SCANCODE_RETURN:
							if(str_cmp(text,"levelup") == 0)
							{
								g->state = LEVELUP;
								Level_Final(g);
							}
							else if(str_cmp(text,"addtime") == 0)
								g->miner.elapsedTime -= 10000;
							
							for(i=0;i<64;i++)
								text[i] = '\0';
							break;
						case SDL_SCANCODE_BACKSPACE:
							for(i=0;i<64;i++)
								if(i != 0 && text[i] == '\0')
									text[i-1] = '\0';
							break;
						default:
							break;
					}
					break;
				case SDL_TEXTINPUT:
					strcat(text, event.text.text);
					break;
			}
		}
		Update_Score_Level(g);
		Do_Render(g);
	}

	SDL_StopTextInput();
	g->miner.curTime = SDL_GetTicks();
}

void Do_Render(Game *g)
{
	int i,j;

	SDL_RenderClear(renderer);

	for(i=0 ; i < g->level->row ; ++i)
	{
		for(j=0 ; j < g->level->column ; ++j)
		{
			g->level->map[i][j].drawingRect.x = g->level->map[i][j].posRect.x - g->miner.cameraRect.x;
			g->level->map[i][j].drawingRect.y = g->level->map[i][j].posRect.y - g->miner.cameraRect.y;
			g->level->map[i][j].drawingRect.w = g->level->map[i][j].posRect.w;
			g->level->map[i][j].drawingRect.h = g->level->map[i][j].posRect.h;
			SDL_RenderCopy(renderer,g->tex,&g->level->map[i][j].cropRect,&g->level->map[i][j].drawingRect);
		}
	}

	if(g->miner.state == ACTIVE)
	{
		g->miner.drawingRect.x = g->miner.posRect.x - g->miner.cameraRect.x;
		g->miner.drawingRect.y = g->miner.posRect.y - g->miner.cameraRect.y;
		g->miner.drawingRect.w = g->miner.posRect.w;
		g->miner.drawingRect.h = g->miner.posRect.h;
		SDL_RenderCopy(renderer,g->miner.tex,&g->miner.cropRect,&g->miner.drawingRect);
	}

	SDL_RenderCopy(renderer,g->panel.tex,&g->panel.cropScore,&g->panel.posScore);
	SDL_RenderCopy(renderer,g->panel.tex,&g->panel.cropTime,&g->panel.posTime);
	SDL_RenderCopy(renderer,g->panel.tex,&g->panel.cropDia,&g->panel.posDia);
	SDL_RenderCopy(renderer,g->panel.tex,&g->panel.cropLevel,&g->panel.posLevel);
	SDL_RenderCopy(renderer,g->panel.tex,&g->panel.cropHealth,&g->panel.posHealth);
	SDL_RenderCopy(renderer,g->panel.textScore,NULL,&g->panel.posTextScore);
	SDL_RenderCopy(renderer,g->panel.textTime,NULL,&g->panel.posTextTime);
	SDL_RenderCopy(renderer,g->panel.textDia,NULL,&g->panel.posTextDia);
	SDL_RenderCopy(renderer,g->panel.textLevel,NULL,&g->panel.posTextLevel);
	SDL_RenderCopy(renderer,g->panel.textHealth,NULL,&g->panel.posTextHealth);
	SDL_RenderPresent(renderer);
}
#